package cn.fzkj.framework.messagequece.config;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.UUID;

/** 消息生产者 */

/**
 * 通过实现 ConfirmCallback 接口，
 * 消息发送到 Broker 后触发回调，确认消息是否到达 Broker 服务器，也就是只确认是否正确到达 Exchange 中
 *
 * 通过实现 ReturnCallback 接口，启动消息失败返回，比如路由不到队列时触发回调
 */
@Component
public class RabbitProducer implements RabbitTemplate.ConfirmCallback, RabbitTemplate.ReturnCallback {

    private final Logger log = LoggerFactory.getLogger(this.getClass());

    //由于rabbitTemplate的scope属性设置为ConfigurableBeanFactory.SCOPE_PROTOTYPE，所以不能自动注入
    private RabbitTemplate rabbitTemplate;

    /**
     * 构造方法注入rabbitTemplate
     */
    @Autowired
    public RabbitProducer(RabbitTemplate rabbitTemplate) {
        this.rabbitTemplate = rabbitTemplate;
        rabbitTemplate.setReturnCallback(this); //rabbitTemplate如果为单例的话，那回调就是最后设置的内容
        rabbitTemplate.setConfirmCallback(this);
    }

    /**
     * 将消息放到和ROUTINFG_KEY绑定的交换机中【配置类中绑定的】
     * 如果要扩展的话，多写几个方法，分别放到不同的交换机中就可以了。
     * */
    // 处理一般消息
    public void sendMessageToClient(String content){
        CorrelationData correlationData = new CorrelationData(UUID.randomUUID().toString());
        // 通过 message.getMessageProperties().getHeaders().get("spring_returned_message_correlation")
        // 可以拿到UUID，这里的uuid是这条消息的id，回调的时候会使用到
        /**
         * convertSendAndReceive(…)：可以同步消费者。使用此方法，
         * 当确认了所有的消费者都接收成功之后，才触发另一个convertSendAndReceive(…)，也就是才会接收下一条消息。RPC调用方式。
         * convertAndSend(…)：使用此方法，交换机会马上把所有的信息都交给所有的消费者，消费者再自行处理，
         * 不会因为消费者处理慢而阻塞线程。
         */
        rabbitTemplate.convertAndSend(
                RabbitConfig.EXCHANGE_DEFAULT_SEVER,
                RabbitConfig.ROUTINGKEY_DEAULT_SERVER,
                content, correlationData);
    }

    // 专门处理redis消息【图片、句子】
    public void tellRedisToGetImgOrWords(String content){
        CorrelationData correlationData = new CorrelationData(UUID.randomUUID().toString());
        rabbitTemplate.convertAndSend(RabbitConfig.EXCHANGE_REDIS_RESOURCE_SERVER, RabbitConfig.ROUTINGKEY_REDIS_RESOURCE_SERVER, content, correlationData);
    }

    // 专门处理redis消息【DB】
    public void tellRedisToDB(String content){
        CorrelationData correlationData = new CorrelationData(UUID.randomUUID().toString());
        rabbitTemplate.convertAndSend(RabbitConfig.EXCHANGE_REDIS_DB_SERVER, RabbitConfig.ROUTINGKEY_REDIS_DB_SERVER, content, correlationData);
    }

    /**
     * 消息确认
     * @param correlationData 消息的唯一标识【上面自己生成的UUID】
     * @param ack 确认结果
     * @param cause 失败原因
     */
    @Override
    public void confirm(CorrelationData correlationData, boolean ack, String cause) {

    }

    @Override
    public void returnedMessage(Message message, int replyCode, String replyText, String exchange, String routingKey) {
        System.out.println("消息主体 message : "+message);
        System.out.println("消息主体 message : "+replyCode);
        System.out.println("描述："+replyText);
        System.out.println("消息使用的交换器 exchange : "+exchange);
        System.out.println("消息使用的路由键 routing : "+routingKey);
    }
}
